package xyz.weizhi.tanhua.appserver.service;

import cn.hutool.core.collection.CollUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import xyz.weizhi.commons.utils.Constants;
import xyz.weizhi.tanhua.appserver.Exception.BusinessException;
import xyz.weizhi.tanhua.appserver.interceptor.UserHolder;
import xyz.weizhi.tanhua.autoconfig.Tempalte.OssTemplate;
import xyz.weizhi.tanhua.dubbo.api.CommentsApi;
import xyz.weizhi.tanhua.dubbo.api.MovementApi;
import xyz.weizhi.tanhua.dubbo.api.UserInfoApi;
import xyz.weizhi.tanhua.model.domain.UserInfo;
import xyz.weizhi.tanhua.model.enums.CommentType;
import xyz.weizhi.tanhua.model.mongo.Comment;
import xyz.weizhi.tanhua.model.mongo.Movement;
import xyz.weizhi.tanhua.model.mongo.MovementTimeLine;
import xyz.weizhi.tanhua.model.vo.ErrorResult;
import xyz.weizhi.tanhua.model.vo.MovementsVo;
import xyz.weizhi.tanhua.model.vo.PageResult;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @Author milian
 * @Date 2021/10/25 0025 20:33
 */
@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private MovementApi movementApi;
    @Autowired
    private RedisTemplate redisTemplate;
    @DubboReference
    private CommentsApi commentsApi;
    // 抽取公共方法封装pageResult
    public PageResult getPageResult(PageResult pr, List<Movement> items, List<Long> userIds) {
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, null);
        ArrayList<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            MovementsVo vo = MovementsVo.init(userInfoMap.get(item.getUserId()), item);
            vos.add(vo);
        }
        pr.setItems(vos);
        return pr;
    }

    /*
        发布个人动态
     */
    public void pubulish(Movement movement, MultipartFile[] files) throws IOException {
        // 判断动态是否有文字动态
        if (StringUtils.isBlank(movement.getTextContent())){
             throw new BusinessException(ErrorResult.contentError());
        }
        // 获取用户id
        Long userId = UserHolder.getId();
        // 上传图片或小视频到阿里云
        ArrayList<String> medias = new ArrayList<>();
        for (MultipartFile file : files) {
            String url = ossTemplate.upload(file.getInputStream(), file.getOriginalFilename());
            medias.add(url);
        }
        // 封装数据
        movement.setUserId(userId);
        movement.setMedias(medias);
        // 调用api保存数据
        movementApi.pubulish(movement);
    }

    /*
        查询个人动态
     */
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        // 判断userId是否为空
        if (userId==null){
            userId = UserHolder.getId();
        }
        // 获取个人动态内容
        PageResult pr = movementApi.findByUserId(userId, page, pagesize);

        List<Movement> items =(List<Movement>) pr.getItems();

        if (items==null||items.size()<=0){
            return pr;
        }
        List<Long> userIds = new ArrayList<>();
        userIds.add(userId);
        return getPageResult(pr, items, userIds);
    }
    /*
        查询好友动态
     */
    public PageResult findByfriendId(Integer page, Integer pagesize) {
        // 获取当前用户Id
        Long userId = UserHolder.getId();
        // 查询好友时间线表,获取动态id集合
        PageResult pr = movementApi.findByfriendId(userId, page, pagesize);


        List<Movement> items = (List<Movement>) pr.getItems();
        // 判空
        if (items==null||items.size()<=0){
            return pr;
        }
        // 查询好友信息，获取好友id集合   TODO 抽取方法
        List<Long> userIds = CollUtil.getFieldValues(items, "userId", Long.class);
        return getPageResult(pr, items, userIds);
    }
    /*
        推荐动态
     */
    public PageResult recommend(Integer page, Integer pagesize) {
        // 获取当前用户id
        Long userId = UserHolder.getId();
        // 从redis数据库获取推荐数据
        String rediskey ="MOVEMENTS_RECOMMEND_"+userId;
        String redisData =(String) redisTemplate.opsForValue().get(rediskey);
        List<Movement> list = Collections.EMPTY_LIST;
        if (StringUtils.isNotEmpty(redisData)){
            // 如果推荐数据不为空
            String[] ids = redisData.split(",");
            //数据不足返回空数据
            if ((page-1)*pagesize>ids.length){
                return new PageResult();
            }
            // 获取当前页码数据
            List<Long> idsList = Arrays.stream(ids).skip((page - 1) * pagesize)
                    .limit(pagesize)
                    .map(e -> Long.parseLong(e))
                    .collect(Collectors.toList());
            // 查询动态
            list = movementApi.findByPids(idsList);
        }else {
            // 推荐数据为空，返回随机数据
            list= movementApi.randomMovements(pagesize);
        }
        if (CollUtil.isEmpty(list)){
            return new PageResult();
        }
        // 获取动态用户id
        List<Long> userIds = CollUtil.getFieldValues(list, "userId",Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, null);
        ArrayList<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = userInfoMap.get(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            vos.add(vo);
        }
        return new PageResult(page,pagesize,0L,vos);
    }
    /*
        根据id查询动态
     */
    public MovementsVo findById(String movementId) {
        Movement movement=movementApi.findByid(movementId);
        if (movement==null){
            return null;
        }
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        return MovementsVo.init(userInfo,movement);
    }

    public Integer operate(String movementId, boolean flag, int type) {
        // 查询用户是否点赞或喜欢
        Boolean hasComment = commentsApi.hasComment(movementId,UserHolder.getId(), type);
        // 判断用户是否重复操作
        if(flag&type==1&hasComment){
            throw new BusinessException(ErrorResult.likeError());
        }else if (flag&type==3&hasComment){
            throw new BusinessException(ErrorResult.loveError());
        }else if (!flag&type==1&!hasComment){
            throw new BusinessException(ErrorResult.disLikeError());
        }else if (!flag&type==3&!hasComment){
            throw new BusinessException(ErrorResult.disloveError());
        }
        // 点赞喜欢操作，将数据保存到comment中
        Integer count;
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey;
        if(flag){
            Comment comment = new Comment();
            comment.setPublishId(new ObjectId(movementId));
            comment.setCommentType(type);
            comment.setUserId(UserHolder.getId());
            comment.setCreated(System.currentTimeMillis());
            // 调用api保存数据
             count = commentsApi.save(comment);
            hashKey= Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getId();
        }else {
            // 取消点赞或取消喜欢
             count = commentsApi.delete(movementId,UserHolder.getId(), type);
            hashKey= Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getId();
        }

        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }
}
